package xin.nick.demo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;

public class DateUtils {
    public static final String[] WEEKS = new String[]{"日", "一", "二", "三", "四", "五", "六"};
    public static final String TO_MONTH = "yyyyMM";
    public static final String TO_DAY = "yyyyMMdd";
    public static final String TO_DAY_SIMPLE = "yyMMdd";
    public static final String TO_HOUR = "yyyyMMddHH";
    public static final String TO_MINUTE = "yyyyMMddHHmm";
    public static final String TO_SECOND = "yyyyMMddHHmmss";
    public static final String TO_MILLISECOND = "yyyyMMddHHmmssSSS";
    public static final String TO_MONTH_LINE = "yyyy-MM";
    public static final String TO_DAY_LINE = "yyyy-MM-dd";
    public static final String TO_HOUR_LINE = "yyyy-MM-dd HH";
    public static final String TO_MINUTE_LINE = "yyyy-MM-dd HH:mm";
    public static final String TO_SECOND_LINE = "yyyy-MM-dd HH:mm:ss";
    public static final String TO_MILLISECOND_LINE = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String TO_MONTH_SLASH = "yyyy/MM";
    public static final String TO_DAY_SLASH = "yyyy/MM/dd";
    public static final String TO_HOUR_SLASH = "yyyy/MM/dd HH";
    public static final String TO_MINUTE_SLASH = "yyyy/MM/dd HH:mm";
    public static final String TO_SECOND_SLASH = "yyyy/MM/dd HH:mm:ss";
    public static final String TO_MILLISECOND_SLASH = "yyyy/MM/dd HH:mm:ss.SSS";
    public static final String TO_MONTH_DOT = "yyyy.MM";
    public static final String TO_DAY_DOT = "yyyy.MM.dd";
    public static final String TO_MINUTE_DOT = "yyyy.MM.dd HH:mm";
    public static final String TO_SECOND_DOT = "yyyy.MM.dd HH:mm:ss";
    public static final String TO_MILLISECOND_DOT = "yyyy.MM.dd HH:mm:ss.SSS";
    public static final String ONLY_YEAR = "yyyy";
    public static final String ONLY_MONTH = "MM";
    public static final String ONLY_MINUTE = "HHmm";
    public static final String ONLY_TIME = "HHmmss";
    public static final String ONLY_TIME_COLON = "HH:mm:ss";
    public static final String MONTH_AND_DAY = "MMdd";
    public static final String MONTH_AND_DAY_LINE = "MM-dd";
    public static final String MONTH_AND_DAY_SLASH = "MM/dd";
    public static final String MONTH_AND_DAY_DOT = "MM.dd";

    private DateUtils() {
    }

    public static Date now() {
        return new Date();
    }

    public static String now(String format) {
        return format(now(), format);
    }

    public static long nowTime() {
        return now().getTime();
    }

    public static long getTime(Date date) {
        return date.getTime();
    }

    public static long todayZeroTime() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MIN).toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    public static long zeroTime(long date) {
        return getTime(format(date, "yyyyMMdd"), "yyyyMMdd");
    }

    public static long getTime(String date, String format) {
        return parse(date, format).getTime();
    }

    public static int get(int field) {
        return get(now(), field);
    }

    public static int get(Date date, int field) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(field);
    }

    public static int[] getPreDays(int n) {
        int[] days = new int[n];
        int today = get(5);
        int preMax = lastDayOfMonth(prevMonth());

        for(int i = 0; i < n; ++i) {
            int day = today - n + 1 + i;
            if (day > 0) {
                days[i] = day;
            } else {
                days[i] = preMax + day;
            }
        }

        return days;
    }

    public static String[] getPreDays(int n, String format) {
        String[] days = new String[n];
        int today = get(5);
        int preMax = lastDayOfMonth(prevMonth());
        String month = format(now(), "MM");
        String preMonth = prevMonth("MM");

        for(int i = 0; i < n; ++i) {
            int day = today - n + 1 + i;
            if (day > 0) {
                days[i] = format(month + day, "MMdd", format);
            } else {
                days[i] = format(preMonth + (preMax + day), "MMdd", format);
            }
        }

        return days;
    }

    public static int getYear() {
        return Calendar.getInstance().get(1);
    }

    public static Date nextYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(1, 1);
        return calendar.getTime();
    }

    public static Date nextYear(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(1, n);
        return calendar.getTime();
    }

    public static Date nextYear(long date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date);
        calendar.add(1, n);
        return calendar.getTime();
    }

    public static int getMonth() {
        return Calendar.getInstance().get(2);
    }

    public static Date nextMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(2, 1);
        return calendar.getTime();
    }

    public static Date nextMonth(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(2, n);
        return calendar.getTime();
    }

    public static Date nextMonth(long date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date);
        calendar.add(2, n);
        return calendar.getTime();
    }

    public static String nextMonth(String format) {
        return format(nextMonth(), format);
    }

    public static Date nextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, 1);
        return calendar.getTime();
    }

    public static String nextMonth(String month, String format) {
        format = format == null || "".equals(format) ? "yyyy-MM" : format;
        Date date = nextMonth( month == null || "".equals(month) ? now() : parse(month, format));
        return format(date, format);
    }

    public static Date prevMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(2, -1);
        return calendar.getTime();
    }

    public static String prevMonth(String format) {
        return format(prevMonth(), format);
    }

    public static Date prevMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, -1);
        return calendar.getTime();
    }

    public static String prevMonth(String month, String format) {
        format = format == null || "".equals(format) ? "yyyy-MM" : format;
        Date date = prevMonth( month == null || "".equals(month) ? now() : parse(month, format));
        return format(date, format);
    }

    public static int lastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(5);
    }

    public static int lastDayOfMonth(String date, String format) {
        return lastDayOfMonth(parse(date, format));
    }

    public static int getDay() {
        return Calendar.getInstance().get(6);
    }

    public static Date nextDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(5, 1);
        return calendar.getTime();
    }

    public static Date nextDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(5, 1);
        return calendar.getTime();
    }

    public static Date nextDay(long date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date(date));
        calendar.add(5, 1);
        return calendar.getTime();
    }

    public static Date nextDay(long date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date);
        calendar.add(5, n);
        return calendar.getTime();
    }

    public static String nextDay(String day, String format) {
        format = format == null || "".equals(format) ? "yyyy-MM-dd" : format;
        Date date = nextDay(day == null || "".equals(day) ? now() : parse(day, format));
        return format(date, format);
    }

    public static long prevDay(int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse(now("yyyyMMdd"), "yyyyMMdd"));
        calendar.add(5, -i);
        return calendar.getTimeInMillis();
    }

    public static String getWeek() {
        return WEEKS[get(7) - 1];
    }

    public static Date parse(String date, String format) {
        if (date == null || "".equals(date)) {
            return new Date();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat(format);

            try {
                return sdf.parse(date);
            } catch (ParseException var4) {
                return null;
            }
        }
    }

    public static long getFirstTimeOfMonth(long time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(5, 1);
        return cal.getTimeInMillis();
    }

    public static long getLastTimeOfMonth(long time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        cal.set(5, cal.getActualMaximum(5));
        cal.set(11, cal.getActualMaximum(11));
        cal.set(12, cal.getActualMaximum(12));
        cal.set(13, cal.getActualMaximum(13));
        return cal.getTimeInMillis();
    }

    public static String format(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static String format(Long timestamp, String format) {
        return timestamp == null ? null : format(new Date(timestamp), format);
    }

    public static String format(String timestamp, String format) {
        return timestamp == null || "".equals(timestamp) ? null : format(Long.valueOf(timestamp), format);
    }

    public static String format(String date, String oldFormat, String newFormat) {
        if (date == null || "".equals(date)) {
            return date;
        } else {
            SimpleDateFormat oldSdf = new SimpleDateFormat(oldFormat);
            SimpleDateFormat newSdf = new SimpleDateFormat(newFormat);

            try {
                return newSdf.format(oldSdf.parse(date));
            } catch (ParseException var6) {
                return date;
            }
        }
    }

    public static String formatDuration(long milliseconds) {
        long s = Math.abs(milliseconds) / 1000L;
        long d = (long)Math.floor((double)(s / 86400L));
        long h = (long)Math.floor((double)(s % 86400L / 3600L));
        long m = (long)Math.floor((double)(s % 86400L % 3600L / 60L));
        s = s % 86400L % 3600L % 60L;
        StringBuilder sb = new StringBuilder("");
        if (d > 0L) {
            sb.append(d + "天");
        }

        if (h > 0L) {
            sb.append(h + "时");
        }

        if (m > 0L) {
            sb.append(m + "分");
        }

        sb.append(s + "秒");
        return sb.toString();
    }

    public static void main(String[] args) {
        long date = getTime("20200414", "yyyyMMdd");
        System.out.println(date);
        long next = nextDay(date, 7).getTime();
        System.out.println(next);
        System.out.println(format(next, "yyyy-MM-dd HH:mm:ss"));
    }
}

